import asyncio
import math
import random

import pygame

import cfg
from debug import debug
from units.uiUtil import gameBgImg, drawText

bg = pygame.image.load('assets/image/bg.png')
# 消消乐精灵数组，0代表消掉了，1，2，3，4种精灵
boxs = []

class MainCollapse:
    def __init__(self, dims, FPS=60):
        self.dims = dims
        self.FPS = FPS
        # 游戏运行控制变量（gamen_running）
        self.game_running = True
        self.score = 0
        self.moveStep = 0

    def checkCollapseRow(self):
        # 先检查横向的
        begainIndex = 0
        begainValue = 0
        count = 1
        for y in range(9,-1,-1):
            for x in range(0,9):
                count = 1
                begainIndex = x
                begainValue = boxs[x][y]
                for z in range(begainIndex+1,10):
                    if begainValue == boxs[z][y]:
                        count += 1
                        # 如果最后一个也相等
                        if z == 9 and count > 2:
                            for n in range(begainIndex,begainIndex+count):
                                boxs[n][y] = 0
                            count = 1
                    else:
                        if count>2:
                            for n in range(begainIndex, begainIndex + count):
                                boxs[n][y] = 0
                        if z<9:
                            begainIndex = z
                            begainValue = boxs[z][y]
                            count = 1
                            break

    def checkCollapseCol(self):
        begainIndex = 0
        begainValue = 0
        count = 1
        for x in range(10):
            for y in range(9):
                count = 1
                begainIndex = y
                begainValue = boxs[x][y]
                for z in range(begainIndex+1,10):
                    if begainValue == boxs[x][z]:
                        count += 1
                        # 如果最后一个也相等
                        if z == 9 and count > 2:
                            for n in range(begainIndex,begainIndex+count):
                                boxs[x][n] = 0
                            count = 1
                    else:
                        if count>2:
                            for n in range(begainIndex,begainIndex+count):
                                boxs[x][n] = 0
                        if z<9:
                            begainIndex = z
                            begainValue = boxs[x][z]
                            count = 1
                            break

    def moveDownCollapse(self):
        for x in range(10):
            for y in range(9, -1, -1):
                if boxs[x][y] == 0:
                    for z in range(y-1,-1,-1):
                        if not boxs[x][z] == 0:
                            boxs[x][y] = boxs[x][z]
                            boxs[x][z] = 0
        # 再循环，将消掉的精灵补齐
        for x in range(10):
            for y in range(10):
                if boxs[x][y] == 0:
                    boxs[x][y] = random.randint(1,4)
                    if self.moveStep>0:
                        self.score +=1

    def checkBox(self, x, y, value):
        # 判断上一个和下一个是否一样
        if y>0 and y<9:
            if boxs[x][y-1] == value and boxs[x][y+1] == value: return True
        # 判断上面两个元素是否和value一样
        if y>1:
            if boxs[x][y-1] == value and boxs[x][y-2] == value: return True
        # 判断下面两个元素是否和value一样
        if y<8:
            if boxs[x][y+1] == value and boxs[x][y+2] == value: return True
        # 判断做一个和右一个是否一样
        if x>0 and x<9:
            if boxs[x-1][y] == value and boxs[x+1][y] == value: return True
        # 判断左两个是否一样
        if x>1:
            if boxs[x-1][y] == value and boxs[x-2][y] == value: return True
        # 判断右两个 是否一样
        if x<8:
            if boxs[x+1][y] == value and boxs[x+2][y] == value: return True

    # 游戏主循环所在函数需要由 async 定义
    async def start(self):
        # 初始化游戏界面（screen）：尺寸、背景色等
        import pygame
        screen = pygame.display.set_mode(self.dims)
        # 显示游戏名称
        pygame.display.set_caption("消消乐")
        # 初始化游戏时钟（clock），由于控制游戏帧率
        clock = pygame.time.Clock()
        # 播放背景音乐
        # playMyBgMusic('')
        # 初始化精灵
        for x in range(10):
            boxs.append([])
            for y in range(10):
                boxs[x].append(random.randint(1,4))
        # 记录当前选中的精灵
        currentSelected = (0,0)

        # 游戏主循环
        while cfg.inGame:
            # 按照给定的 FPS 刷新游戏
            # clock.tick() 函数返回上一次调用该函数后经历的时间，单位为毫秒 ms
            # dt 记录上一帧接受之后经历的时间，单位为秒 m
            # 使用 dt 控制物体运动可以使游戏物理过程与帧率无关
            dt = clock.tick(self.FPS) / 1000.0
            # 使用 asyncio 同步
            # 此外游戏主体代码中不需要再考虑 asyncio
            await asyncio.sleep(0)

            # 以背景色覆盖刷新游戏界面
            gameBgImg(screen, bg, 270, self.dims)

            # 调用 debug 函数在游戏界面左上角显示游戏帧率
            debug(f"{clock.get_fps():.1f}", color='green')
            # 显示分数
            drawText(f'移动步数：{self.moveStep} 步  消除精灵：{self.score}个', "black", (50, 100), screen)

            # 画游戏界面
            if self.game_running:
                # 绘制网格
                for y in range(11):
                    pygame.draw.line(screen, "white", (110, 400 + 50 * y),(110+500,400 + 50 * y))
                for x in range(11):
                    pygame.draw.line(screen, "white", (110+50*x, 400),(110+50*x,400+500))
                # 给当前选中的精灵加背景色
                pygame.draw.rect(screen, (240, 255, 240), ((110+50*currentSelected[0]),(400+50*currentSelected[1]), 50, 50))
                # 绘制精灵
                for x in range(10):
                    for y in range(10):
                        box_x = 110 + 50 * x
                        box_y = 400 + 50 * y
                        if boxs[x][y] == 1:
                            pygame.draw.rect(screen, (255, 246, 143), (box_x+5, box_y+5, 40, 40))
                        elif boxs[x][y] == 2:
                            pygame.draw.circle(screen,(127, 255, 212),(box_x+25, box_y+25),20)
                        elif boxs[x][y] == 3:
                            pygame.draw.polygon(screen,(245, 222, 179),((box_x+25, box_y+5),(box_x+5,box_y+45),(box_x+45,box_y+45)))
                        elif boxs[x][y] == 4:
                            pygame.draw.ellipse(screen, (255, 165, 79), (box_x+5, box_y+15, 40, 20))
                # 检测，横向，竖向有3个或3个以上一样的直接消除
                self.checkCollapseRow()
                self.checkCollapseCol()
                self.moveDownCollapse()

            # 游戏事件处理
            # 包括键盘、鼠标输入等
            for event in pygame.event.get():
                # 点击关闭窗口按钮或关闭网页
                if event.type == pygame.QUIT:
                    pygame.quit()
                # 鼠标点击事件
                if event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_presses  = pygame.mouse.get_pos()
                    # 根据鼠标坐标反向算出哪个精灵被点击了
                    clicked_x = math.floor((mouse_presses[0]-110)/50)
                    clicked_y = math.floor((mouse_presses[1]-400)/50)
                    if clicked_x>9: clicked_x = 9
                    if clicked_y>9: clicked_y = 9
                    # 判断当前选中的和上一次选中的精灵是否挨着
                    if not (clicked_x == currentSelected[0] and clicked_y == currentSelected[1]):
                        if (clicked_x-currentSelected[0] == 1 or clicked_x-currentSelected[0] == -1) and clicked_y == currentSelected[1]:
                            currntValue = boxs[currentSelected[0]][currentSelected[1]]
                            clickedValue = boxs[clicked_x][clicked_y]
                            canchange1 = self.checkBox(clicked_x,clicked_y,currntValue)
                            canchange2 = self.checkBox(currentSelected[0], currentSelected[1], clickedValue)
                            if canchange1 or canchange2:
                                self.moveStep +=1
                                boxs[currentSelected[0]][currentSelected[1]] = clickedValue
                                boxs[clicked_x][clicked_y] = currntValue
                        if (clicked_y-currentSelected[1] == 1 or clicked_y-currentSelected[1] == -1) and clicked_x == currentSelected[0]:
                            currntValue = boxs[currentSelected[0]][currentSelected[1]]
                            clickedValue = boxs[clicked_x][clicked_y]
                            canchange1 = self.checkBox(clicked_x, clicked_y, currntValue)
                            canchange2 = self.checkBox(currentSelected[0], currentSelected[1], clickedValue)
                            if canchange1 or canchange2:
                                self.moveStep += 1
                                boxs[currentSelected[0]][currentSelected[1]] = clickedValue
                                boxs[clicked_x][clicked_y] = currntValue
                        else:
                            currentSelected = (clicked_x,clicked_y)
            # 将游戏界面内容输出至屏幕
            pygame.display.update()

        # 跳出游戏主循环，退出游戏
        cfg.inGame = False